#ifndef __LINX_RANDOM_IN_H
#define __LINX_RANDOM_IN_H
#include "random.h"
#include <errno.h>
#include <stdint.h>
#include <stdio.h>

/* --- random.c --- */

int _linx_random_init(const void* nonce, const int nlen,
    const char* str, const int strlen);

int _linx_random_reseed(const void* es, const int eslen,
    const void* ex, const int ex_len);

int _linx_random(const void* ex_in, const int len,
    unsigned char* random, const unsigned int rlen);

/* --- entropy_source.c --- */

#define SYS_ENTROPY_LEN 1024

int read_entropy_sys(unsigned char* random, const int len);
int read_entropy_dev(unsigned char* random, const int len);
int read_entropy_cpu(unsigned char* random, const int len);

/* --- random_sm3.c --- */

#define SEEDLEN  440 // bits, 55 byte
#define SEEDLEN_BITS    SEEDLEN
#define SEEDLEN_BYTES  (SEEDLEN / 8) // bits
#define reseed_interval_in_time 60 //second
#define reseed_interval_in_counter (1<<10)
#define min_entropy 256 /* bits */
#define min_entropy_bits min_entropy
#define min_entropy_bytes (min_entropy_bits / 8)
#define min_entropy_input_length 256 //bits
#define max_entropy_input_length (1UL<<35) //bits
#define number_of_bits_to_return SEEDLEN_BITS
#define number_of_bytes_to_return SEEDLEN_BYTES

/**
 * @brief 内部状态
 * 
 * @V 每次随机数生成时会进行更新
 * @C 每次重播时会进行更新
 * @reseed_counter 在初始化和重播种之后，请求随机数的次数
 * @last_reseed_time 上次重播种时间
 */
struct internal_state
{
    unsigned char V[SEEDLEN_BYTES];
    unsigned char C[SEEDLEN_BYTES];
    int reseed_counter;
    unsigned long last_reseed_time;
};
typedef struct internal_state internal_state_t;

int leftmost(unsigned char* V, const int a, unsigned char* out);
int get_entropy(unsigned char* entropy, const long len);
int sm3_df(const unsigned char* str, const int slen, unsigned char* out);
int sm3_rng_instantiate(const char* str, const int slen,
    const void* noise, const int nlen);
int sm3_rng_reseed(const unsigned char* entropy, const int elen,
    const unsigned char* opt, const int optlen);
int sm3_rng_generate( const void* opt, const int optlen,
    unsigned char out[32]);
long get_current_time_in_second();

/* --- entropy_pool.c --- */

#define ENTROPY_POOL_LEN_WORDS 128
#define ENTROPY_POOL_LEN_BYTES (ENTROPY_POOL_LEN_WORDS*4)
// 1 字等于 4字节

int entropy_pool_update(uint32_t* g, const int len);
unsigned char* get_entropy_pool();

/* --- entropy_estimate.c --- */

int entropy_estimate(unsigned int* entropy_bits);

/* --- entropy_hc.c --- */

int _recount_test();
int _adaptive_scale_test();

/* --- random_state.c --- */

int sys_entropy_counter_add();
int sys_entropy_counter_reset();
int sys_entropy_counter_get();
int sys_entropy_counter_arrived();

#define RANDOM_STATE_INIT 0x1
#define RANDOM_STATE_WORK 0x2
#define RANDOM_STATE_ERROR 0x4

int random_state_get();
int random_state_set(int state);
int random_state_is(int state);

#endif /* __LINX_RANDOM_IN_H */